﻿//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;
//using FFmpeg.AutoGen;
//using OpenTK.Audio.OpenAL;

//namespace MediaLib
//{
//    public unsafe class OpenALUtilities : IDisposable
//    {
//        public bool Initialization { get; private set; }

//        private ALDevice _device;
//        private ALContext _context;
//        private int _sid;

//        public OpenALUtilities()
//        {
//            Init();
//        }

//        public bool Init()
//        {
//            if (Initialization) { return true; }
//            lock (this)
//            {
//                if (Initialization) { return true; }
//                ALError err = OpenDevice(out _device, out _context);
//                if (err != ALError.NoError) { return false; }

//                AL.GenSources(1, ref _sid);
//                AL.Source(_sid, ALSourcef.Pitch, 1f);
//                AL.Source(_sid, ALSourcef.Gain, 1f);
//                AL.Source(_sid, ALSourcef.ReferenceDistance, 1f);
//                AL.Source(_sid, ALSource3f.Position, 0f, 0f, 0f);
//                AL.Source(_sid, ALSource3f.Velocity, 0f, 0f, 0f);
//                //AL.Source(_sid, ALSource3f.Direction, 0f, 0f, 0f);
//                AL.Source(_sid, ALSourceb.Looping, false);
//                AL.Source(_sid, ALSourcei.SourceType, (int)ALSourceType.Static);
//                AL.SpeedOfSound(343.3f);
//                AL.DopplerFactor(1f);
//                AL.DistanceModel(ALDistanceModel.LinearDistance);
//                AL.Listener(ALListener3f.Position, 0f, 0f, 0f);
//                return true;
//            }
//        }

//        public void SourcePause() => AL.SourcePause(_sid);

//        public void SourcePlay() => AL.SourcePlay(_sid);

//        public void SourceStop() => AL.SourceStop(_sid);

//        public void SourceRewind() => AL.SourceRewind(_sid);

//        public void SetVolume(float vol) => AL.Source(_sid, ALSourcef.Gain, vol);

//        public void SetSpeed(float speed = 1f) => AL.SpeedOfSound(speed);

//        public void QueueBuffer(void* buffer, int size, ALFormat fmt, int sampleRate)
//        {
//            int bufferId = AL.GenBuffer();
//            AL.BufferData(bufferId, fmt, buffer, size, sampleRate);
//            AL.SourceQueueBuffers(_sid, 1, &bufferId);
//        }

//        /// <summary>
//        /// 队列里已执行完的buffer数量
//        /// </summary>
//        /// <returns></returns>
//        public int BuffersProcessed()
//        {
//            AL.GetSource(_sid, ALGetSourcei.BuffersProcessed, out int processedNum);
//            return processedNum;
//        }

//        /// <summary>
//        /// 队列里未执行的buffer数量
//        /// </summary>
//        /// <returns></returns>
//        public int BuffersQueued()
//        {
//            AL.GetSource(_sid, ALGetSourcei.BuffersQueued, out int queuedNum);
//            return queuedNum;
//        }

//        public ALSourceState GetSourceState()
//        {
//            AL.GetSource(_sid, ALGetSourcei.SourceState, out int status);
//            return (ALSourceState)status;
//        }


//        /// <summary>
//        /// 检查并清除已播放的缓存
//        /// </summary>
//        public void ClearUnqueueBuffers()
//        {
//            AL.GetSource(_sid, ALGetSourcei.BuffersProcessed, out int processdNum);
//            if (processdNum > 0)
//            {
//                uint[] bids = new uint[processdNum];
//                int[] cacheBids = new int[processdNum];
//                AL.SourceUnqueueBuffers(_sid, processdNum, cacheBids);
//                AL.DeleteBuffers(cacheBids);
//            }
//        }


//        #region
//        /// <summary>
//        /// 打开音频播放设备
//        /// </summary>
//        /// <param name="device"></param>
//        /// <param name="context"></param>
//        /// <returns></returns>
//        public static ALError OpenDevice(out ALDevice device, out ALContext context)
//        {
//            context = ALContext.Null;
//            device = ALC.OpenDevice(null);
//            if (device.Handle == IntPtr.Zero) { return AL.GetError(); }
//            ALContextAttributes ctxAttr = new ALContextAttributes();
//            context = ALC.CreateContext(device, ctxAttr);
//            if (context.Handle == IntPtr.Zero) { return AL.GetError(); }
//            _ = ALC.MakeContextCurrent(context);
//            return AL.GetError();
//        }

//        public void CloseDevice()
//        {
//            ALC.CloseDevice(_device);
//            ALC.DestroyContext(_context);

//        }
//        #endregion

//        #region Dispose
//        private bool disposedValue;

//        protected virtual void Dispose(bool disposing)
//        {
//            if (!disposedValue)
//            {
//                if (disposing)
//                {
//                    // TODO: 释放托管状态(托管对象)
//                }

//                // TODO: 释放未托管的资源(未托管的对象)并重写终结器
//                // TODO: 将大型字段设置为 null
//                disposedValue = true;
//            }
//        }

//        public void Dispose()
//        {
//            // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
//            Dispose(disposing: true);
//            GC.SuppressFinalize(this);
//        }
//        #endregion

//    }

//    /// <summary>
//    /// 
//    /// </summary>
//    public static class OpenALExtension
//    {
//        #region 基于OpenTK.OpenAL实现
//        /// <summary>
//        /// 打开音频播放设备
//        /// </summary>
//        /// <param name="device"></param>
//        /// <param name="context"></param>
//        /// <returns></returns>
//        public static ALError OpenDevice(out ALDevice device, out ALContext context)
//        {
//            context = ALContext.Null;
//            device = ALC.OpenDevice(null);
//            if (device.Handle == IntPtr.Zero) { return AL.GetError(); }
//            ALContextAttributes ctxAttr = new ALContextAttributes();
//            context = ALC.CreateContext(device, ctxAttr);
//            if (context.Handle == IntPtr.Zero) { return AL.GetError(); }
//            _ = ALC.MakeContextCurrent(context);
//            return AL.GetError();
//        }

//        /// <summary>
//        /// 获取音频类型
//        /// </summary>
//        /// <param name="channel"></param>
//        /// <param name="depthBit"></param>
//        /// <returns></returns>
//        public static ALFormat GetALFormat(int channel, int depthBit)
//        {
//            ALFormat fmt = 0;
//            if (channel == 1)
//            {
//                if (depthBit == 8)
//                    fmt = ALFormat.Mono8;
//                else if (depthBit == 16)
//                    fmt = ALFormat.Mono16;
//                else if (depthBit == 32)
//                    fmt = ALFormat.MonoFloat32Ext;
//            }
//            else if (channel == 2)
//            {
//                if (depthBit == 8)
//                    fmt = ALFormat.Stereo8;
//                else if (depthBit == 16)
//                    fmt = ALFormat.Stereo16;
//                else if (depthBit == 32)
//                    fmt = ALFormat.StereoFloat32Ext;
//            }
//            else if (AL.IsExtensionPresent("AL_EXT_MCFORMATS"))
//            {
//                if (depthBit == 8)
//                {
//                    if (channel == 4)
//                        fmt = (ALFormat)AL.GetEnumValue("AL_FORMAT_QUAD8");
//                    else if (channel == 6)
//                        fmt = (ALFormat)AL.GetEnumValue("AL_FORMAT_51CHN8");
//                }
//                else if (depthBit == 16)
//                {
//                    if (channel == 4)
//                        fmt = (ALFormat)AL.GetEnumValue("AL_FORMAT_QUAD16");
//                    else if (channel == 6)
//                        fmt = (ALFormat)AL.GetEnumValue("AL_FORMAT_51CHN16");
//                }
//            }
//            return fmt;
//        }


//        public static ValueTuple<AVSampleFormat, ALFormat> AVSampleFmtToALFmt(AVSampleFormat in_fmt, int channels)
//        {
//            ALFormat out_ALFmt = 0;
//            AVSampleFormat av_fmt = AVSampleFormat.AV_SAMPLE_FMT_NONE;

//            switch (in_fmt)
//            {
//                case AVSampleFormat.AV_SAMPLE_FMT_U8:
//                case AVSampleFormat.AV_SAMPLE_FMT_U8P:
//                    av_fmt = AVSampleFormat.AV_SAMPLE_FMT_U8;
//                    if (channels == 1)
//                        out_ALFmt = ALFormat.Mono8;
//                    else if (channels == 2)
//                        out_ALFmt = ALFormat.Stereo8;
//                    break;
//                case AVSampleFormat.AV_SAMPLE_FMT_S16:
//                case AVSampleFormat.AV_SAMPLE_FMT_S16P:
//                    av_fmt = AVSampleFormat.AV_SAMPLE_FMT_S16;
//                    if (channels == 1)
//                        out_ALFmt = ALFormat.Mono16;
//                    else if (channels == 2)
//                        out_ALFmt = ALFormat.Stereo16;
//                    break;
//                case AVSampleFormat.AV_SAMPLE_FMT_S32:
//                case AVSampleFormat.AV_SAMPLE_FMT_S32P:
//                    av_fmt = AVSampleFormat.AV_SAMPLE_FMT_S16;
//                    if (channels == 1)
//                        out_ALFmt = ALFormat.Mono16;
//                    else if (channels == 2)
//                        out_ALFmt = ALFormat.Stereo16;
//                    break;
//                case AVSampleFormat.AV_SAMPLE_FMT_FLT:
//                case AVSampleFormat.AV_SAMPLE_FMT_FLTP:
//                    av_fmt = AVSampleFormat.AV_SAMPLE_FMT_FLT;
//                    if (channels == 1)
//                        out_ALFmt = ALFormat.MonoFloat32Ext;
//                    else if (channels == 2)
//                        out_ALFmt = ALFormat.StereoFloat32Ext;
//                    break;
//                case AVSampleFormat.AV_SAMPLE_FMT_S64:
//                case AVSampleFormat.AV_SAMPLE_FMT_S64P:
//                    av_fmt = AVSampleFormat.AV_SAMPLE_FMT_S64P;
//                    if (channels == 1)
//                        out_ALFmt = ALFormat.MonoALawExt;
//                    else if (channels == 2)
//                        out_ALFmt = ALFormat.MonoMuLawExt;
//                    break;
//                case AVSampleFormat.AV_SAMPLE_FMT_DBL:
//                case AVSampleFormat.AV_SAMPLE_FMT_DBLP:
//                    av_fmt = AVSampleFormat.AV_SAMPLE_FMT_DBL;
//                    if (channels == 1)
//                        out_ALFmt = ALFormat.MonoDoubleExt;
//                    else if (channels == 2)
//                        out_ALFmt = ALFormat.StereoDoubleExt;
//                    break;
//                default:
//                    break;
//            }
//            return (av_fmt, out_ALFmt);
//        }

//        #endregion

//    }
//}